/*
 * Copyright 2010 WANdisco, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. 
 */
package com.googlecode.svnj.reports;

import java.io.IOException;
import java.io.OutputStream;

import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.googlecode.svnj.IDeltaEditor;
import com.googlecode.svnj.RepoContext;
import com.googlecode.svnj.XMLUtil;

public class XMLDeltaEditor extends StaxHelper implements IDeltaEditor {

    private static final Logger log = LoggerFactory.getLogger(XMLDeltaEditor.class);
    
    RepoContext ctx;
    private long targetRev = -1;
    
    public XMLDeltaEditor(OutputStream os, RepoContext ctx)
    throws IOException,XMLStreamException {
        this.ctx = ctx;
        stream = XMLUtil.initWriter(os, "S:update-report");
        stream.writeAttribute("send-all", "true");
    }
    public void abortEdit() throws Exception  {
        stream.flush();
        stream.close();
    }

    public void absentDirectory(String path) throws Exception  {
        emptyElem("S:absent-directory");
        att("name", path);
    }

    public void absentFile(String path) throws Exception  {
        emptyElem("S:absent-file");
        att("name", path);
    }

    public void addDirectory(String path, String copyFromPath,
            long copyFromRevision) throws Exception  {
        elem("S:add-directory");
        att("name", path);
        if (copyFromPath != null) {
            att("copyfrom-path", copyFromPath);
            att("copyfrom-rev", String.valueOf(copyFromRevision));
        }
    }

    public void addFile(String path, String copyFromPath, long copyFromRevision)
    throws Exception {
        elem("S:add-file");
        att("name", path);
        if (copyFromPath != null) {
            att("copyfrom-path", copyFromPath);
            att("copyfrom-rev", String.valueOf(copyFromRevision));
        }
    }

    public void appendTextDelta(String deltaStr) throws Exception  {
        stream.writeCharacters(deltaStr);
    }

    public void beginTextDelta(String baseChecksum) throws Exception  {
        elem("S:txdelta");
    }

    public void endTextDelta()  throws Exception {
        end();
    }

    public void changeDirProp(String name, String value) throws Exception  {
        elem("S:set-prop");
        att("name", name);
        stream.writeCharacters(value);
        end();
    }

    public void changeFileProp(String name, String value) throws Exception  {
        elem("S:set-prop");
        att("name", name);
        stream.writeCharacters(value);
        end();
    }

    public void closeDirectory() throws Exception  {
        end();
    }

    public void closeEdit() throws Exception {
        stream.flush();
        end();
        stream.writeEndDocument();
        stream.flush();
        stream.close();
    }

    public void closeFile(String txtChecksum) throws Exception  {
        if (txtChecksum != null) {
            elem("S:prop");
            elem("V:md5-checksum");
            stream.writeCharacters(txtChecksum);
            end();
            end();
        }
        end();
    }

    public void deleteEntry(String path, long revision) throws Exception {
        emptyElem("S:delete-entry");
        att("name", path);
    }

    public void openDirectory(String path, long baseRevision) throws Exception {
        elem("S:open-directory");
        if (path != null)
            att("name", path);
        att("rev", String.valueOf(baseRevision));
        this.versionHref(path, this.targetRev);
    }

    public void openFile(String path, long baseRevision) throws Exception  {
        elem("S:open-file");
        att("name", path);
        att("rev", String.valueOf(baseRevision));
        this.versionHref(path, this.targetRev);
    }

    public void openRoot(long revision) throws Exception  {
        elem("S:open-directory");
        att("rev", String.valueOf(revision));
    }

    public void setTargetRevision(long revision) throws Exception  {
        //xml.writeStartElement("S:target-revision");
        emptyElem("S:target-revision");
        att("rev", String.valueOf(revision));
        this.targetRev = revision;
    }

    /*
    private void elem(String name) throws Exception {
        xml.writeStartElement(name);
    }
    private void emptyElem(String name) throws Exception {
        xml.writeEmptyElement(name);
    }
    private void att(String name, String val) throws Exception {
        xml.writeAttribute(name, val);
    }
    private void end() throws Exception {
        xml.writeEndElement();
    }
    */
    private void versionHref(String path, long rev) throws Exception {
        elem("D:checked-in");
        elem("D:href");
        stream.writeCharacters(ctx.getContextPath() + "/!svn/ver/"
                + targetRev + "/" + path);
        end();
        end();
    }

    /*
    public static void main(String[] a) throws Exception {
        XMLOutputFactory fac = XMLOutputFactory.newInstance();
        //fac.setProperty("indent", "true");
        //p("indent? " + fac.isPropertySupported("INDENT"));
        XMLStreamWriter w = fac.createXMLStreamWriter(System.out);
        System.err.println("is a " + w.getClass().getName());
        w.writeStartDocument();
        XMLUtil.initialize(w, "S:update-report");
        w.writeAttribute("send-all", "true");
        w.writeEndElement();
        w.writeEndDocument();
        System.out.flush();
    }*/
}
